`include "PRV564Config.v"
`include "PRV564Define.v"
/*****************************************************************************************
 *    author : Jack's Team
 *    e-mail : 
 *    date   : 20210726
 *    desc   : PRV564 kernal Top level file
 *    version: 0001
 
Family 	: PRV5
Module 	: 564 Top module
Arch    : Vostok
ISA		: RISC-V 64bit Extension U,S,I,M,A,F,D,X
L1I		: 16K 4 Way Set Associative NRU
L1D		: 32K 8 Way Set Associative NRU
TLB-I	: Automatic 32-entry TLB-I              //default
TLB-D	: Automatic 32-entry TLB-D              //default

 __  __                   __           __         
/\ \/\ \                 /\ \__       /\ \        
\ \ \ \ \    ___     ____\ \ ,_\   ___\ \ \/'\    
 \ \ \ \ \  / __`\  /',__\\ \ \/  / __`\ \ , <    
  \ \ \_/ \/\ \L\ \/\__, `\\ \ \_/\ \L\ \ \ \\`\  
   \ `\___/\ \____/\/\____/ \ \__\ \____/\ \_\ \_\
    `\/__/  \/___/  \/___/   \/__/\/___/  \/_/\/_/


    This is a 64bit RISC-V processor

   "I see Earth! It is so beautiful!"
                        —— Yuri Gagarin

**********************************************************************************************/
module PRV564_top
#(parameter HART_ID=8'h00,
            ITLB_FIBID=8'h01,
            DTLB_FIBID=8'h02,
            ICACHE_FIBID=8'h03,
            DCACHE_FIBID=8'h04,
            L1I_WAYNUM=1,
            L1D_WAYNUM=1
)
(
    input wire                  GLB_CLKi,
    input wire                  GLB_ARSTi,
//----------------Flexible Interconnection Bus----------
    output  wire                ITLB_FIB_WRENo, DTLB_FIB_WRENo,        //write to DTLB_FIB enable
    output  wire                ITLB_FIB_REQo,  DTLB_FIB_REQo,        //request DTLB_FIB trans
    input   wire                ITLB_FIB_ACKi,  DTLB_FIB_ACKi,        //request acknowledge
    input   wire                ITLB_FIB_FULLi, DTLB_FIB_FULLi,       //DTLB_FIB FIFO full
    output  wire [7:0]          ITLB_FIB_IDo,   DTLB_FIB_IDo,
    output  wire [7:0]          ITLB_FIB_CMDo,  DTLB_FIB_CMDo,
    output  wire [3:0]          ITLB_FIB_BURSTo,DTLB_FIB_BURSTo,
    output  wire [3:0]          ITLB_FIB_SIZEo, DTLB_FIB_SIZEo,
    output  wire [`PADR-1:0]    ITLB_FIB_ADDRo, DTLB_FIB_ADDRo,    
    output  wire [`XLEN-1:0]    ITLB_FIB_DATAo, DTLB_FIB_DATAo,
    input   wire [7:0]          ITLB_FIB_IDi,   DTLB_FIB_IDi,
    input   wire [7:0]          ITLB_FIB_RPLi,  DTLB_FIB_RPLi,
    input   wire                ITLB_FIB_Vi,    DTLB_FIB_Vi,
    input   wire [`XLEN-1:0]    ITLB_FIB_DATAi, DTLB_FIB_DATAi,
//CPU Cache FIB
    output  wire                ICache_FIB_WRENo, DCache_FIB_WRENo,        //write to DCache_FIB enable
    output  wire                ICache_FIB_REQo,  DCache_FIB_REQo,        //request DCache_FIB trans
    input   wire                ICache_FIB_ACKi,  DCache_FIB_ACKi,        //request acknowledge
    input   wire                ICache_FIB_FULLi, DCache_FIB_FULLi,       //DCache_FIB FIFO full
    output  wire [7:0]          ICache_FIB_IDo,   DCache_FIB_IDo,
    output  wire [7:0]          ICache_FIB_CMDo,  DCache_FIB_CMDo,
    output  wire [3:0]          ICache_FIB_BURSTo,DCache_FIB_BURSTo,
    output  wire [3:0]          ICache_FIB_SIZEo, DCache_FIB_SIZEo,
    output  wire [`PADR-1:0]    ICache_FIB_ADDRo, DCache_FIB_ADDRo,    
    output  wire [`XLEN-1:0]    ICache_FIB_DATAo, DCache_FIB_DATAo,
    input   wire [7:0]          ICache_FIB_IDi,   DCache_FIB_IDi,
    input   wire [7:0]          ICache_FIB_RPLi,  DCache_FIB_RPLi,
    input   wire                ICache_FIB_Vi,    DCache_FIB_Vi,
    input   wire [`XLEN-1:0]    ICache_FIB_DATAi, DCache_FIB_DATAi,
//---------------Interrupt signal-------------------------
    input wire                  Kernel_MTIi,        //Machine mode timer interrupt
    input wire                  Kernel_MSIi,        //Machine mode software interrupt
    input wire                  Kernel_MEIi,        //Machine mode ext interrupt
    input wire                  Kernel_SEIi,        //Supervisior mode ext interrupt
    input wire                  Kernel_NMIPLi,      //Power lost!
    input wire                  Kernel_NMIEEi,      //Ecc Error
    input wire                  Kernel_NMIGi,       //General purpose
//--------------Machine mode timer-----------------------
    input wire [63:0]           Kernel_MTIMEi	    //Machine mode timer value in
);
//----------------------cache access queue------------------------
    wire                 ICache_AQ_V,      DCache_AQ_V;
    wire [7:0]           ICache_AQ_ID,     DCache_AQ_ID;
    wire [7:0]           ICache_AQ_CMD,    DCache_AQ_CMD;
    wire                 ICache_AQ_CI,     DCache_AQ_CI;
    wire                 ICache_AQ_WT,     DCache_AQ_WT;
    wire [15:0]          ICache_AQ_BSEL,   DCache_AQ_BSEL;
    wire [127:0]                           DCache_AQ_WDATA;
    wire [`PADR-1:0]     ICache_AQ_ADDR,   DCache_AQ_ADDR;
    wire                 ICache_AQ_FULL,   DCache_AQ_FULL;
    wire                 ICache_RQ_V,      DCache_RQ_V;
    wire [7:0]           ICache_RQ_ID,     DCache_RQ_ID;
    wire                 ICache_RQ_WRERR,  DCache_RQ_WRERR;
    wire                 ICache_RQ_RDERR,  DCache_RQ_RDERR;
    wire                 ICache_RQ_RDY,    DCache_RQ_RDY;
    wire [127:0]         ICache_RQ_RDATA,  DCache_RQ_RDATA;
    wire                 ICache_RQ_ACK,    DCache_RQ_ACK;
//--------------------Sink for NOT-matched address----------------------------
    wire [`XLEN-`PADR-1:0]IAQ_ADDR_SINK,   DAQ_ADDR_SINK;
    wire [`XLEN-`PADR-1:0]ITLB_ADDR_SINK,  DTLB_ADDR_SINK;
`ifdef WAVEDUMP
initial 
begin
    $dumpfile("./temp/Vostok564_dbg.vcd");
    $dumpvars();
end
`endif
PRV564_Kernel #(
    .HARTID                     (HART_ID),
    .ITLB_FIBID                 (ITLB_FIBID),
    .DTLB_FIBID                 (DTLB_FIBID))
Kernel(
    .Kernel_CLKi                (GLB_CLKi),
    .Kernel_ARSTi               (GLB_ARSTi),
//---------------TLB Access port---------------------------
    .ITLB_FIBo_WREN             (ITLB_FIB_WRENo),        //write to FIB1 enable
    .ITLB_FIBo_REQ              (ITLB_FIB_REQo),         //request FIB1 trans
    .ITLB_FIBi_ACK              (ITLB_FIB_ACKi),         //request acknowledge
    .ITLB_FIBi_FULL             (ITLB_FIB_FULLi),        //FIB1 FIFO full
    .ITLB_FIBo_ID               (ITLB_FIB_IDo),
    .ITLB_FIBo_CMD              (ITLB_FIB_CMDo),
    .ITLB_FIBo_BURST            (ITLB_FIB_BURSTo),
    .ITLB_FIBo_SIZE             (ITLB_FIB_SIZEo),
    .ITLB_FIBo_ADDR             ({ITLB_ADDR_SINK,ITLB_FIB_ADDRo}),      
    .ITLB_FIBo_DATA             (ITLB_FIB_DATAo),
    .ITLB_FIBi_ID               (ITLB_FIB_IDi),
    .ITLB_FIBi_RPL              (ITLB_FIB_RPLi),
    .ITLB_FIBi_V                (ITLB_FIB_Vi),
    .ITLB_FIBi_DATA             (ITLB_FIB_DATAi),
    //---------------FIB0-----------------
    .DTLB_FIBo_WREN             (DTLB_FIB_WRENo),        //write to FIB0 enable
    .DTLB_FIBo_REQ              (DTLB_FIB_REQo),         //request FIB0 trans
    .DTLB_FIBi_ACK              (DTLB_FIB_ACKi),         //request acknowledge
    .DTLB_FIBi_FULL             (DTLB_FIB_FULLi),        //FIB0 FIFO full
    .DTLB_FIBo_ID               (DTLB_FIB_IDo),
    .DTLB_FIBo_CMD              (DTLB_FIB_CMDo),
    .DTLB_FIBo_BURST            (DTLB_FIB_BURSTo),
    .DTLB_FIBo_SIZE             (DTLB_FIB_SIZEo),
    .DTLB_FIBo_ADDR             ({DTLB_ADDR_SINK,DTLB_FIB_ADDRo}),      
    .DTLB_FIBo_DATA             (DTLB_FIB_DATAo),
    .DTLB_FIBi_ID               (DTLB_FIB_IDi),
    .DTLB_FIBi_RPL              (DTLB_FIB_RPLi),
    .DTLB_FIBi_V                (DTLB_FIB_Vi),
    .DTLB_FIBi_DATA             (DTLB_FIB_DATAi),
//----------------To cache port---------------------------
    .ICache_AQ_V                (ICache_AQ_V),      
    .DCache_AQ_V                (DCache_AQ_V),
    .ICache_AQ_ID               (ICache_AQ_ID),     
    .DCache_AQ_ID               (DCache_AQ_ID),
    .ICache_AQ_CMD              (ICache_AQ_CMD),    
    .DCache_AQ_CMD              (DCache_AQ_CMD),
    .ICache_AQ_CI               (ICache_AQ_CI),     
    .DCache_AQ_CI               (DCache_AQ_CI),
    .ICache_AQ_WT               (ICache_AQ_WT),     
    .DCache_AQ_WT               (DCache_AQ_WT),
    .ICache_AQ_BSEL             (ICache_AQ_BSEL),   
    .DCache_AQ_BSEL             (DCache_AQ_BSEL),
    .DCache_AQ_WDATA            (DCache_AQ_WDATA),
    .ICache_AQ_ADDR             ({IAQ_ADDR_SINK,ICache_AQ_ADDR}),   
    .DCache_AQ_ADDR             ({DAQ_ADDR_SINK,DCache_AQ_ADDR}),
    .ICache_AQ_FULL             (ICache_AQ_FULL),   
    .DCache_AQ_FULL             (DCache_AQ_FULL),
    .ICache_RQ_V                (ICache_RQ_V),      
    .DCache_RQ_V                (DCache_RQ_V),
    .ICache_RQ_ID               (ICache_RQ_ID),     
    .DCache_RQ_ID               (DCache_RQ_ID),
    .ICache_RQ_WRERR            (ICache_RQ_WRERR),  
    .DCache_RQ_WRERR            (DCache_RQ_WRERR),
    .ICache_RQ_RDERR            (ICache_RQ_RDERR),  
    .DCache_RQ_RDERR            (DCache_RQ_RDERR),
    .ICache_RQ_RDY              (ICache_RQ_RDY),    
    .DCache_RQ_RDY              (DCache_RQ_RDY),
    .ICache_RQ_RDATA            (ICache_RQ_RDATA),  
    .DCache_RQ_RDATA            (DCache_RQ_RDATA),
    .ICache_RQ_ACK              (ICache_RQ_ACK),    
    .DCache_RQ_ACK              (DCache_RQ_ACK),
    .Kernel_MTIi                (Kernel_MTIi),        //Machine mode timer interrupt
    .Kernel_MSIi                (Kernel_MSIi),        //Machine mode software interrupt
    .Kernel_MEIi                (Kernel_MEIi),        //Machine mode ext interrupt
    .Kernel_SEIi                (Kernel_SEIi),        //Supervisior mode ext interrupt
    .Kernel_NMIPLi              (Kernel_NMIPLi),      //Power lost!
    .Kernel_NMIEEi              (Kernel_NMIEEi),      //Ecc Error
    .Kernel_NMIGi               (Kernel_NMIGi),       //General purpose
    .Kernel_MTIMEi              (Kernel_MTIMEi)	      //Machine mode timer value in
);
//-------------------------------------------Cache-------------------------------------------
L1I #(
  .WAY_NUM          (L1I_WAYNUM),
  .CACHE_FIBID      (ICACHE_FIBID),
  .SRAM_BANKCOEFF   (4)
  )
L1I(
    .GLB_CLKi                   (GLB_CLKi),
    .GLB_RSTi                   (GLB_ARSTi),                      //Cache冲刷请求
    //Access Queue
    .AQ_V                       (ICache_AQ_V),
    .AQ_ID                      (ICache_AQ_ID),
    .AQ_CMD                     (ICache_AQ_CMD),
    .AQ_BSEL                    (ICache_AQ_BSEL),
    .AQ_CI                      (ICache_AQ_CI),//1'b1
    .AQ_WT                      (ICache_AQ_WT),
    .AQ_WDATA                   (128'h0),
    .AQ_ADDR                    (ICache_AQ_ADDR),
    .AQ_FULL                    (ICache_AQ_FULL),
    //Respond Queue
    .RQ_V                       (ICache_RQ_V),
    .RQ_ID                      (ICache_RQ_ID),
    .RQ_WRERR                   (ICache_RQ_WRERR),
    .RQ_RDERR                   (ICache_RQ_RDERR),
    .RQ_RDY                     (ICache_RQ_RDY),
    .RQ_RDATA                   (ICache_RQ_RDATA),
    .RQ_ACK                     (ICache_RQ_ACK),
    //To FIB
    .L1_FIBo_REQ                (ICache_FIB_REQo),
    .L1_FIBo_WREN               (ICache_FIB_WRENo),
    .L1_FIBo_ID                 (ICache_FIB_IDo),
    .L1_FIBo_CMD                (ICache_FIB_CMDo),
    .L1_FIBo_BURST              (ICache_FIB_BURSTo),
    .L1_FIBo_SIZE               (ICache_FIB_SIZEo),
    .L1_FIBo_ADDR               (ICache_FIB_ADDRo),
    .L1_FIBo_DATA               (ICache_FIB_DATAo),
    .L1_FIBi_FULL               (ICache_FIB_FULLi),
    .L1_FIBi_V                  (ICache_FIB_Vi),
    .L1_FIBi_ACK                (ICache_FIB_ACKi),
    .L1_FIBi_ID                 (ICache_FIB_IDi),
    .L1_FIBi_RPL                (ICache_FIB_RPLi),
    .L1_FIBi_DATA               (ICache_FIB_DATAi)
);
L1D #(
  .WAY_NUM              (L1D_WAYNUM),
  .CACHE_FIBID          (DCACHE_FIBID),
  .SRAM_BANKCOEFF   (4)
  )
L1D(
    .GLB_CLKi                   (GLB_CLKi),
    .GLB_RSTi                   (GLB_ARSTi),                      //Cache冲刷请求
    //Access Queue1'b1
    .AQ_V                       (DCache_AQ_V),
    .AQ_ID                      (DCache_AQ_ID),
    .AQ_CMD                     (DCache_AQ_CMD),
    .AQ_BSEL                    (DCache_AQ_BSEL),
    .AQ_CI                      (DCache_AQ_CI),// 
    .AQ_WT                      (DCache_AQ_WT),//
    .AQ_WDATA                   (DCache_AQ_WDATA),
    .AQ_ADDR                    (DCache_AQ_ADDR),
    .AQ_FULL                    (DCache_AQ_FULL),
    //Respond Queue
    .RQ_V                       (DCache_RQ_V),
    .RQ_ID                      (DCache_RQ_ID),
    .RQ_WRERR                   (DCache_RQ_WRERR),
    .RQ_RDERR                   (DCache_RQ_RDERR),
    .RQ_RDY                     (DCache_RQ_RDY),
    .RQ_RDATA                   (DCache_RQ_RDATA),
    .RQ_ACK                     (DCache_RQ_ACK),
    //To FIB
    .L1_FIBo_REQ                (DCache_FIB_REQo),
    .L1_FIBo_WREN               (DCache_FIB_WRENo),
    .L1_FIBo_ID                 (DCache_FIB_IDo),
    .L1_FIBo_CMD                (DCache_FIB_CMDo),
    .L1_FIBo_BURST              (DCache_FIB_BURSTo),
    .L1_FIBo_SIZE               (DCache_FIB_SIZEo),
    .L1_FIBo_ADDR               (DCache_FIB_ADDRo),
    .L1_FIBo_DATA               (DCache_FIB_DATAo),
    .L1_FIBi_FULL               (DCache_FIB_FULLi),
    .L1_FIBi_V                  (DCache_FIB_Vi),
    .L1_FIBi_ACK                (DCache_FIB_ACKi),
    .L1_FIBi_ID                 (DCache_FIB_IDi),
    .L1_FIBi_RPL                (DCache_FIB_RPLi),
    .L1_FIBi_DATA               (DCache_FIB_DATAi)
);
//------------------------Bus monitor------------------------
//  TODO remove this always block before ASIC flow 
`ifdef STUCK_AUTO_STOP
always@(posedge GLB_CLKi)begin
    if(DCache_AQ_V& `DEBUG_RUN)begin
        $display("DCache AQ:ID=%h, CMD=%h, ADDR=%h, DATA=%h",DCache_AQ_ID, DCache_AQ_CMD, DCache_AQ_ADDR, DCache_AQ_WDATA);
    end

    if(DCache_RQ_V & `DEBUG_RUN)begin
        $display("DCache RQ:ID=%h, ERR=%h, DATA=%h",DCache_RQ_ID, DCache_RQ_RDERR, DCache_RQ_RDATA);
    end
end
`endif
endmodule

